package net.zdsoft.wpchat.support.service.impl;

import java.io.IOException;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import net.zdsoft.keel.util.Validators;
import net.zdsoft.wpchat.support.dao.SqlTaskDao;
import net.zdsoft.wpchat.support.entity.ResultPack;
import net.zdsoft.wpchat.support.entity.SqlTaskStep;
import net.zdsoft.wpchat.support.exception.SqlParseException;
import net.zdsoft.wpchat.support.service.SqlTaskService;

import org.springframework.stereotype.Service;

/**
 * sql语法执行service
 *
 * @author xuan
 */
@Service
public class SqlTaskServiceImpl implements SqlTaskService {
	@Resource
	private SqlTaskDao sqlTaskDao;

	@Override
	public String[] splitSql(String sqlStatement, boolean slashComments)
			throws IOException {
		if (!sqlStatement.endsWith(";")) {
			sqlStatement += ";";
		}

		Reader r = new StringReader(sqlStatement);
		StreamTokenizer token = new StreamTokenizer(r);
		// token.commentChar('-');
		token.resetSyntax();// 重置此标记生成器的语法表，使所有字符都成为“普通”字符。
		token.slashStarComments(slashComments);// 确定标记生成器是否识别 C 样式注释。
		token.quoteChar('\'');// 指定此字符的匹配对分隔此标记生成器中的字符串常量

		List<String> sqlList = new ArrayList<String>();
		StringBuffer sb = new StringBuffer();

		int flag = StreamTokenizer.TT_EOF;
		while (StreamTokenizer.TT_EOF != (flag = token.nextToken())) {
			switch (flag) {
			case StreamTokenizer.TT_NUMBER:
				sb.append(token.nval);
				break;
			case StreamTokenizer.TT_WORD:
				sb.append(token.sval);
				break;
			case '\'':
				sb.append('\'').append(token.sval).append('\'');
				break;
			case SqlTaskStep.TASK_SEPARATOR:
				if ((!sb.toString().trim().startsWith("--") || !slashComments)
						&& !Validators.isBlank(sb.toString().trim())) {
					sqlList.add(sb.toString());
				}
				sb = new StringBuffer();
				break;
			default:
				sb.append((char) token.ttype);
				break;
			}
		}
		return sqlList.toArray(new String[0]);
	}

	@Override
	public ResultPack[] executeQuery(String sqlStatement, int pageNum)
			throws SqlParseException {
		if (Validators.isEmpty(sqlStatement)) {
			return null;
		}

		String[] sqls;
		try {
			sqls = splitSql(sqlStatement, true);
			List<String> sqlList = new ArrayList<String>();
			for (String sql : sqls) {
				if (!Validators.isEmpty(sql)) {
					sqlList.add(sql);
				}
			}
			sqls = sqlList.toArray(new String[0]);
		} catch (IOException e) {
			throw new SqlParseException("SQL 语句解析异常");
		}

		ResultPack[] packs = new ResultPack[sqls.length];
		if (pageNum < sqls.length) {
			packs[pageNum] = sqlTaskDao.executeQuery(sqls[pageNum]);
		}
		return packs;
	}

	@Override
	public int[] executeUpdate(String sqlContent) throws SqlParseException {
		String[] sqls;
		try {
			sqls = splitSql(sqlContent, true);
		} catch (IOException e) {
			throw new SqlParseException("SQL 语句解析异常");
		}

		int[] resultCodes = new int[sqls.length];
		for (int i = 0; i < sqls.length; i++) {
			resultCodes[i] = sqlTaskDao.executeUpdate(sqls[i]);
		}
		return resultCodes;
	}

}
